home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.exp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-25  |  13.5 KB  |  704 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.exp.c,v 3.1 1991/07/15 19:37:24 christos Exp $ */
  2. /*
  3.  * sh.exp.c: Expression evaluations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: sh.exp.c,v 3.1 1991/07/15 19:37:24 christos Exp $")
  39.  
  40. #include "sh.h"
  41.  
  42. /*
  43.  * C shell
  44.  */
  45.  
  46. #define IGNORE    1    /* in ignore, it means to ignore value, just parse */
  47. #define NOGLOB    2    /* in ignore, it means not to globone */
  48.  
  49. #define    ADDOP    1
  50. #define    MULOP    2
  51. #define    EQOP    4
  52. #define    RELOP    8
  53. #define    RESTOP    16
  54. #define    ANYOP    31
  55.  
  56. #define    EQEQ    1
  57. #define    GTR    2
  58. #define    LSS    4
  59. #define    NOTEQ    6
  60. #define EQMATCH 7
  61. #define NOTEQMATCH 8
  62.  
  63. static    int     exp1    __P((Char ***, bool));
  64. static    int     exp2    __P((Char ***, bool));
  65. static    int     exp2a    __P((Char ***, bool));
  66. static    int     exp2b    __P((Char ***, bool));
  67. static    int     exp2c    __P((Char ***, bool));
  68. static    Char     *exp3    __P((Char ***, bool));
  69. static    Char     *exp3a    __P((Char ***, bool));
  70. static    Char     *exp4    __P((Char ***, bool));
  71. static    Char     *exp5    __P((Char ***, bool));
  72. static    Char     *exp6    __P((Char ***, bool));
  73. static    void     evalav    __P((Char **));
  74. static    int     isa    __P((Char *, int));
  75. static    int     egetn    __P((Char *));
  76.  
  77. #ifdef EDEBUG
  78. static    void     etracc    __P((char *, Char *, Char ***));
  79. static    void     etraci    __P((char *, int, Char ***));
  80. #endif
  81.  
  82. int
  83. exp(vp)
  84.     register Char ***vp;
  85. {
  86.     return (exp0(vp, 0));
  87. }
  88.  
  89. int
  90. exp0(vp, ignore)
  91.     register Char ***vp;
  92.     bool    ignore;
  93. {
  94.     register int p1 = exp1(vp, ignore);
  95.  
  96. #ifdef EDEBUG
  97.     etraci("exp0 p1", p1, vp);
  98. #endif
  99.     if (**vp && eq(**vp, STRor2)) {
  100.     register int p2;
  101.  
  102.     (*vp)++;
  103.     p2 = exp0(vp, (ignore & IGNORE) || p1);
  104. #ifdef EDEBUG
  105.     etraci("exp0 p2", p2, vp);
  106. #endif
  107.     return (p1 || p2);
  108.     }
  109.     return (p1);
  110. }
  111.  
  112. static int
  113. exp1(vp, ignore)
  114.     register Char ***vp;
  115.     bool    ignore;
  116. {
  117.     register int p1 = exp2(vp, ignore);
  118.  
  119. #ifdef EDEBUG
  120.     etraci("exp1 p1", p1, vp);
  121. #endif
  122.     if (**vp && eq(**vp, STRand2)) {
  123.     register int p2;
  124.  
  125.     (*vp)++;
  126.     p2 = exp1(vp, (ignore & IGNORE) || !p1);
  127. #ifdef EDEBUG
  128.     etraci("exp1 p2", p2, vp);
  129. #endif
  130.     return (p1 && p2);
  131.     }
  132.     return (p1);
  133. }
  134.  
  135. static int
  136. exp2(vp, ignore)
  137.     register Char ***vp;
  138.     bool    ignore;
  139. {
  140.     register int p1 = exp2a(vp, ignore);
  141.  
  142. #ifdef EDEBUG
  143.     etraci("exp3 p1", p1, vp);
  144. #endif
  145.     if (**vp && eq(**vp, STRor)) {
  146.     register int p2;
  147.  
  148.     (*vp)++;
  149.     p2 = exp2(vp, ignore);
  150. #ifdef EDEBUG
  151.     etraci("exp3 p2", p2, vp);
  152. #endif
  153.     return (p1 | p2);
  154.     }
  155.     return (p1);
  156. }
  157.  
  158. static int
  159. exp2a(vp, ignore)
  160.     register Char ***vp;
  161.     bool    ignore;
  162. {
  163.     register int p1 = exp2b(vp, ignore);
  164.  
  165. #ifdef EDEBUG
  166.     etraci("exp2a p1", p1, vp);
  167. #endif
  168.     if (**vp && eq(**vp, STRcaret)) {
  169.     register int p2;
  170.  
  171.     (*vp)++;
  172.     p2 = exp2a(vp, ignore);
  173. #ifdef EDEBUG
  174.     etraci("exp2a p2", p2, vp);
  175. #endif
  176.     return (p1 ^ p2);
  177.     }
  178.     return (p1);
  179. }
  180.  
  181. static int
  182. exp2b(vp, ignore)
  183.     register Char ***vp;
  184.     bool    ignore;
  185. {
  186.     register int p1 = exp2c(vp, ignore);
  187.  
  188. #ifdef EDEBUG
  189.     etraci("exp2b p1", p1, vp);
  190. #endif
  191.     if (**vp && eq(**vp, STRand)) {
  192.     register int p2;
  193.  
  194.     (*vp)++;
  195.     p2 = exp2b(vp, ignore);
  196. #ifdef EDEBUG
  197.     etraci("exp2b p2", p2, vp);
  198. #endif
  199.     return (p1 & p2);
  200.     }
  201.     return (p1);
  202. }
  203.  
  204. static int
  205. exp2c(vp, ignore)
  206.     register Char ***vp;
  207.     bool    ignore;
  208. {
  209.     register Char *p1 = exp3(vp, ignore);
  210.     register Char *p2;
  211.     register int i;
  212.  
  213. #ifdef EDEBUG
  214.     etracc("exp2c p1", p1, vp);
  215. #endif
  216.     if (i = isa(**vp, EQOP)) {
  217.     (*vp)++;
  218.     if (i == EQMATCH || i == NOTEQMATCH)
  219.         ignore |= NOGLOB;
  220.     p2 = exp3(vp, ignore);
  221. #ifdef EDEBUG
  222.     etracc("exp2c p2", p2, vp);
  223. #endif
  224.     if (!(ignore & IGNORE))
  225.         switch (i) {
  226.  
  227.         case EQEQ:
  228.         i = eq(p1, p2);
  229.         break;
  230.  
  231.         case NOTEQ:
  232.         i = !eq(p1, p2);
  233.         break;
  234.  
  235.         case EQMATCH:
  236.         i = Gmatch(p1, p2);
  237.         break;
  238.  
  239.         case NOTEQMATCH:
  240.         i = !Gmatch(p1, p2);
  241.         break;
  242.         }
  243.     xfree((ptr_t) p1);
  244.     xfree((ptr_t) p2);
  245.     return (i);
  246.     }
  247.     i = egetn(p1);
  248.     xfree((ptr_t) p1);
  249.     return (i);
  250. }
  251.  
  252. static Char *
  253. exp3(vp, ignore)
  254.     register Char ***vp;
  255.     bool    ignore;
  256. {
  257.     register Char *p1, *p2;
  258.     register int i;
  259.  
  260.     p1 = exp3a(vp, ignore);
  261. #ifdef EDEBUG
  262.     etracc("exp3 p1", p1, vp);
  263. #endif
  264.     if (i = isa(**vp, RELOP)) {
  265.     (*vp)++;
  266.     if (**vp && eq(**vp, STRequal))
  267.         i |= 1, (*vp)++;
  268.     p2 = exp3(vp, ignore);
  269. #ifdef EDEBUG
  270.     etracc("exp3 p2", p2, vp);
  271. #endif
  272.     if (!(ignore & IGNORE))
  273.         switch (i) {
  274.  
  275.         case GTR:
  276.         i = egetn(p1) > egetn(p2);
  277.         break;
  278.  
  279.         case GTR | 1:
  280.         i = egetn(p1) >= egetn(p2);
  281.         break;
  282.  
  283.         case LSS:
  284.         i = egetn(p1) < egetn(p2);
  285.         break;
  286.  
  287.         case LSS | 1:
  288.         i = egetn(p1) <= egetn(p2);
  289.         break;
  290.         }
  291.     xfree((ptr_t) p1);
  292.     xfree((ptr_t) p2);
  293.     return (putn(i));
  294.     }
  295.     return (p1);
  296. }
  297.  
  298. static Char *
  299. exp3a(vp, ignore)
  300.     register Char ***vp;
  301.     bool    ignore;
  302. {
  303.     register Char *p1, *p2, *op;
  304.     register int i;
  305.  
  306.     p1 = exp4(vp, ignore);
  307. #ifdef EDEBUG
  308.     etracc("exp3a p1", p1, vp);
  309. #endif
  310.     op = **vp;
  311.     if (op && any("<>", op[0]) && op[0] == op[1]) {
  312.     (*vp)++;
  313.     p2 = exp3a(vp, ignore);
  314. #ifdef EDEBUG
  315.     etracc("exp3a p2", p2, vp);
  316. #endif
  317.     if (op[0] == '<')
  318.         i = egetn(p1) << egetn(p2);
  319.     else
  320.         i = egetn(p1) >> egetn(p2);
  321.     xfree((ptr_t) p1);
  322.     xfree((ptr_t) p2);
  323.     return (putn(i));
  324.     }
  325.     return (p1);
  326. }
  327.  
  328. static Char *
  329. exp4(vp, ignore)
  330.     register Char ***vp;
  331.     bool    ignore;
  332. {
  333.     register Char *p1, *p2;
  334.     register int i = 0;
  335.  
  336.     p1 = exp5(vp, ignore);
  337. #ifdef EDEBUG
  338.     etracc("exp4 p1", p1, vp);
  339. #endif
  340.     if (isa(**vp, ADDOP)) {
  341.     register Char *op = *(*vp)++;
  342.  
  343.     p2 = exp4(vp, ignore);
  344. #ifdef EDEBUG
  345.     etracc("exp4 p2", p2, vp);
  346. #endif
  347.     if (!(ignore & IGNORE))
  348.         switch (op[0]) {
  349.  
  350.         case '+':
  351.         i = egetn(p1) + egetn(p2);
  352.         break;
  353.  
  354.         case '-':
  355.         i = egetn(p1) - egetn(p2);
  356.         break;
  357.         }
  358.     xfree((ptr_t) p1);
  359.     xfree((ptr_t) p2);
  360.     return (putn(i));
  361.     }
  362.     return (p1);
  363. }
  364.  
  365. static Char *
  366. exp5(vp, ignore)
  367.     register Char ***vp;
  368.     bool    ignore;
  369. {
  370.     register Char *p1, *p2;
  371.     register int i = 0;
  372.  
  373.     p1 = exp6(vp, ignore);
  374. #ifdef EDEBUG
  375.     etracc("exp5 p1", p1, vp);
  376. #endif
  377.     if (isa(**vp, MULOP)) {
  378.     register Char *op = *(*vp)++;
  379.  
  380.     p2 = exp5(vp, ignore);
  381. #ifdef EDEBUG
  382.     etracc("exp5 p2", p2, vp);
  383. #endif
  384.     if (!(ignore & IGNORE))
  385.         switch (op[0]) {
  386.  
  387.         case '*':
  388.         i = egetn(p1) * egetn(p2);
  389.         break;
  390.  
  391.         case '/':
  392.         i = egetn(p2);
  393.         if (i == 0)
  394.             stderror(ERR_DIV0);
  395.         i = egetn(p1) / i;
  396.         break;
  397.  
  398.         case '%':
  399.         i = egetn(p2);
  400.         if (i == 0)
  401.             stderror(ERR_MOD0);
  402.         i = egetn(p1) % i;
  403.         break;
  404.         }
  405.     xfree((ptr_t) p1);
  406.     xfree((ptr_t) p2);
  407.     return (putn(i));
  408.     }
  409.     return (p1);
  410. }
  411.  
  412. static Char *
  413. exp6(vp, ignore)
  414.     register Char ***vp;
  415.     bool    ignore;
  416. {
  417.     int     ccode, i = 0;
  418.     register Char *cp, *dp, *ep;
  419.  
  420.     if (**vp == 0)
  421.     stderror(ERR_NAME | ERR_EXPRESSION);
  422.     if (eq(**vp, STRbang)) {
  423.     (*vp)++;
  424.     cp = exp6(vp, ignore);
  425. #ifdef EDEBUG
  426.     etracc("exp6 ! cp", cp, vp);
  427. #endif
  428.     i = egetn(cp);
  429.     xfree((ptr_t) cp);
  430.     return (putn(!i));
  431.     }
  432.     if (eq(**vp, STRtilde)) {
  433.     (*vp)++;
  434.     cp = exp6(vp, ignore);
  435. #ifdef EDEBUG
  436.     etracc("exp6 ~ cp", cp, vp);
  437. #endif
  438.     i = egetn(cp);
  439.     xfree((ptr_t) cp);
  440.     return (putn(~i));
  441.     }
  442.     if (eq(**vp, STRLparen)) {
  443.     (*vp)++;
  444.     ccode = exp0(vp, ignore);
  445. #ifdef EDEBUG
  446.     etraci("exp6 () ccode", ccode, vp);
  447. #endif
  448.     if (*vp == 0 || **vp == 0 || ***vp != ')')
  449.         stderror(ERR_NAME | ERR_EXPRESSION);
  450.     (*vp)++;
  451.     return (putn(ccode));
  452.     }
  453.     if (eq(**vp, STRLbrace)) {
  454.     register Char **v;
  455.     struct command faket;
  456.     Char   *fakecom[2];
  457.  
  458.     faket.t_dtyp = NODE_COMMAND;
  459.     faket.t_dflg = 0;
  460.     faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
  461.     faket.t_dcom = fakecom;
  462.     fakecom[0] = STRfakecom;
  463.     fakecom[1] = NOSTR;
  464.     (*vp)++;
  465.     v = *vp;
  466.     for (;;) {
  467.         if (!**vp)
  468.         stderror(ERR_NAME | ERR_MISSING, '}');
  469.         if (eq(*(*vp)++, STRRbrace))
  470.         break;
  471.     }
  472.     if (ignore & IGNORE)
  473.         return (Strsave(STRNULL));
  474.     psavejob();
  475.     if (pfork(&faket, -1) == 0) {
  476.         *--(*vp) = 0;
  477.         evalav(v);
  478.         exitstat();
  479.     }
  480.     pwait();
  481.     prestjob();
  482. #ifdef EDEBUG
  483.     etraci("exp6 {} status", egetn(value(STRstatus)), vp);
  484. #endif
  485.     return (putn(egetn(value(STRstatus)) == 0));
  486.     }
  487.     if (isa(**vp, ANYOP))
  488.     return (Strsave(STRNULL));
  489.     cp = *(*vp)++;
  490.     if (*cp == '-' && any("erwxfdzopls", cp[1])) {
  491.     struct stat stb;
  492.  
  493.     if (cp[2] != '\0')
  494.         stderror(ERR_NAME | ERR_FILEINQ);
  495.     /*
  496.      * Detect missing file names by checking for operator in the file name
  497.      * position.  However, if an operator name appears there, we must make
  498.      * sure that there's no file by that name (e.g., "/") before announcing
  499.      * an error.  Even this check isn't quite right, since it doesn't take
  500.      * globbing into account.
  501.      */
  502.     if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
  503.         stderror(ERR_NAME | ERR_FILENAME);
  504.  
  505.     dp = *(*vp)++;
  506.     if (ignore & IGNORE)
  507.         return (Strsave(STRNULL));
  508.     ep = globone(dp, G_ERROR);
  509.     switch (cp[1]) {
  510.  
  511.     case 'r':
  512.         i = !access(short2str(ep), R_OK);
  513.         break;
  514.  
  515.     case 'w':
  516.         i = !access(short2str(ep), W_OK);
  517.         break;
  518.  
  519.     case 'x':
  520.         i = !access(short2str(ep), X_OK);
  521.         break;
  522.  
  523.     default:
  524.         if (
  525. #ifdef S_IFLNK
  526.         cp[1] == 'l' ? lstat(short2str(ep), &stb) :
  527. #endif
  528.         stat(short2str(ep), &stb)) {
  529.         xfree((ptr_t) ep);
  530.         return (Strsave(STR0));
  531.         }
  532.         switch (cp[1]) {
  533.  
  534.         case 'f':
  535.         i = S_ISREG(stb.st_mode);
  536.         break;
  537.  
  538.         case 'd':
  539.         i = S_ISDIR(stb.st_mode);
  540.         break;
  541.  
  542.         case 'p':
  543. #ifdef S_ISFIFO
  544.         i = S_ISFIFO(stb.st_mode);
  545. #else
  546.         i = 0;
  547. #endif
  548.         break;
  549.  
  550.         case 'l':
  551. #ifdef S_ISLNK
  552.         i = S_ISLNK(stb.st_mode);
  553. #else
  554.         i = 0;
  555. #endif
  556.         break;
  557.  
  558.         case 's':
  559. #ifdef S_ISSOCK
  560.         i = S_ISSOCK(stb.st_mode);
  561. #else
  562.         i = 0;
  563. #endif
  564.         break;
  565.  
  566.         case 'z':
  567.         i = stb.st_size == 0;
  568.         break;
  569.  
  570.         case 'e':
  571.         i = 1;
  572.         break;
  573.  
  574.         case 'o':
  575.         i = stb.st_uid == uid;
  576.         break;
  577.         }
  578.     }
  579. #ifdef EDEBUG
  580.     etraci("exp6 -? i", i, vp);
  581. #endif
  582.     xfree((ptr_t) ep);
  583.     return (putn(i));
  584.     }
  585. #ifdef EDEBUG
  586.     etracc("exp6 default", cp, vp);
  587. #endif
  588.     return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
  589. }
  590.  
  591. static void
  592. evalav(v)
  593.     register Char **v;
  594. {
  595.     struct wordent paraml1;
  596.     register struct wordent *hp = ¶ml1;
  597.     struct command *t;
  598.     register struct wordent *wdp = hp;
  599.  
  600.     set(STRstatus, Strsave(STR0));
  601.     hp->prev = hp->next = hp;
  602.     hp->word = STRNULL;
  603.     while (*v) {
  604.     register struct wordent *new =
  605.     (struct wordent *) xcalloc(1, sizeof *wdp);
  606.  
  607.     new->prev = wdp;
  608.     new->next = hp;
  609.     wdp->next = new;
  610.     wdp = new;
  611.     wdp->word = Strsave(*v++);
  612.     }
  613.     hp->prev = wdp;
  614.     alias(¶ml1);
  615.     t = syntax(paraml1.next, ¶ml1, 0);
  616.     if (seterr)
  617.     stderror(ERR_OLD);
  618.     execute(t, -1, NULL, NULL);
  619.     freelex(¶ml1), freesyn(t);
  620. }
  621.  
  622. static int
  623. isa(cp, what)
  624.     register Char *cp;
  625.     register int what;
  626. {
  627.     if (cp == 0)
  628.     return ((what & RESTOP) != 0);
  629.     if (cp[1] == 0) {
  630.     if (what & ADDOP && (*cp == '+' || *cp == '-'))
  631.         return (1);
  632.     if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
  633.         return (1);
  634.     if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
  635.                   *cp == '~' || *cp == '^' || *cp == '"'))
  636.         return (1);
  637.     }
  638.     else if (cp[2] == 0) {
  639.     if (what & RESTOP) {
  640.         if (cp[0] == '|' && cp[1] == '&')
  641.         return (1);
  642.         if (cp[0] == '<' && cp[1] == '<')
  643.         return (1);
  644.         if (cp[0] == '>' && cp[1] == '>')
  645.         return (1);
  646.     }
  647.     if (what & EQOP) {
  648.         if (cp[0] == '=') {
  649.         if (cp[1] == '=')
  650.             return (EQEQ);
  651.         if (cp[1] == '~')
  652.             return (EQMATCH);
  653.         }
  654.         else if (cp[0] == '!') {
  655.         if (cp[1] == '=')
  656.             return (NOTEQ);
  657.         if (cp[1] == '~')
  658.             return (NOTEQMATCH);
  659.         }
  660.     }
  661.     }
  662.     if (what & RELOP) {
  663.     if (*cp == '<')
  664.         return (LSS);
  665.     if (*cp == '>')
  666.         return (GTR);
  667.     }
  668.     return (0);
  669. }
  670.  
  671. static int
  672. egetn(cp)
  673.     register Char *cp;
  674. {
  675.     if (*cp && *cp != '-' && !Isdigit(*cp))
  676.     stderror(ERR_NAME | ERR_EXPRESSION);
  677.     return (getn(cp));
  678. }
  679.  
  680. /* Phew! */
  681.  
  682. #ifdef EDEBUG
  683. static void
  684. etraci(str, i, vp)
  685.     char   *str;
  686.     int     i;
  687.     Char ***vp;
  688. {
  689.     xprintf("%s=%d\t", str, i);
  690.     blkpr(*vp);
  691.     xprintf("\n");
  692. }
  693. static void
  694. etracc(str, cp, vp)
  695.     char   *str;
  696.     Char   *cp;
  697.     Char ***vp;
  698. {
  699.     xprintf("%s=%s\t", str, cp);
  700.     blkpr(*vp);
  701.     xprintf("\n");
  702. }
  703. #endif
  704.